package com.geek.javase.ch13.videodemo.serial;

import java.io.*;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @Desc TODO
 * @Author chenmin
 * @Date 2025/10/25
 *
 * 防止序列化数据被篡改！
 * 1.序列化时给对象生成一个hash值
 * 2.反序列化时，再次为对象生成hash值，做比对
 * 3.若发生改变则抛出异常阻止篡改
 */
public class SerialDemo {

    //序列化
    public static void serial(){
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt"))){
            oos.writeObject(new Person("李四" , 22));
            oos.flush();
            System.out.println("序列化完成~");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //反序列化
    public static void unserial(){
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"))){
            Person p = (Person)ois.readObject();
            System.out.println("p = "+p);
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        //serial();
        unserial();
    }

}
class Person implements Serializable {

    private static final long serialVersionUID = -4884483041835235689L;


    private String name;
    private int age;

    //防伪码
    private String hash;

    //生成hash值的算法  MD5加密
    public String getHash() {
        String str = name+age;
        //通过MD5方式，更新信息的字符串
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.update(str.getBytes(Charset.defaultCharset()));
            //转成字节数组
            byte[] bytes = messageDigest.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : bytes) {
                //转成16进制
                sb.append(String.format("%02X", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "error hash";
    }

    public void setHash(String hash) {
        this.hash = getHash();
    }

    //定义方法，放置篡改文件信息
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        //默认读取数据
        in.defaultReadObject();
        //System.out.println("this = "+this);

        //获取文本中的hash值 新
        String newHash = this.getHash();
        //原来存储至文本上的hash值  旧
        String oldHash = this.hash;
        //比对
        if(!newHash.equals(oldHash)){
            //被篡改信息了，则抛出异常进行阻止和提醒
            throw new IllegalArgumentException("对象信息被篡改了，请重新生成！");
        }
    }


    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        this.hash = getHash();
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Person{name = " + name + ", age = " + age + "}";
    }
}
